package org.onionframework.persistence.dao.functions.date;


public class DatePartternUtils {

	/**
	 * The compiled pattern.
	 */
	transient private char[] compiledPattern;

	static final String patternChars = "GyMdkHmsSEDFwWahKzZ";

	/**
	 * Tags for the compiled pattern.
	 */
	private final static int TAG_QUOTE_ASCII_CHAR = 100;
	private final static int TAG_QUOTE_CHARS = 101;

	/**
	 * 这段代码来自JDK的SimpleDateFormat类，把日期Pattern转化为一个
	 * char数组，其中存放了格式信息。
	 * 
	 * 写的时候看懂过，写完了就看不懂了
	 * 
	 * @param pattern
	 * @return
	 */
	public char[] compile(String pattern) {
		int length = pattern.length();
		boolean inQuote = false;
		StringBuilder compiledPattern = new StringBuilder(length * 2);
		StringBuilder tmpBuffer = null;
		int count = 0;
		int lastTag = -1;

		for (int i = 0; i < length; i++) {
			char c = pattern.charAt(i);

			if (c == '\'') {
				// '' is treated as a single quote regardless of being
				// in a quoted section.
				if ((i + 1) < length) {
					c = pattern.charAt(i + 1);
					if (c == '\'') {
						i++;
						if (count != 0) {
							encode(lastTag, count, compiledPattern);
							lastTag = -1;
							count = 0;
						}
						if (inQuote) {
							tmpBuffer.append(c);
						} else {
							compiledPattern
									.append((char) (TAG_QUOTE_ASCII_CHAR << 8 | c));
						}
						continue;
					}
				}
				if (!inQuote) {
					if (count != 0) {
						encode(lastTag, count, compiledPattern);
						lastTag = -1;
						count = 0;
					}
					if (tmpBuffer == null) {
						tmpBuffer = new StringBuilder(length);
					} else {
						tmpBuffer.setLength(0);
					}
					inQuote = true;
				} else {
					int len = tmpBuffer.length();
					if (len == 1) {
						char ch = tmpBuffer.charAt(0);
						if (ch < 128) {
							compiledPattern
									.append((char) (TAG_QUOTE_ASCII_CHAR << 8 | ch));
						} else {
							compiledPattern
									.append((char) (TAG_QUOTE_CHARS << 8 | 1));
							compiledPattern.append(ch);
						}
					} else {
						encode(TAG_QUOTE_CHARS, len, compiledPattern);
						compiledPattern.append(tmpBuffer);
					}
					inQuote = false;
				}
				continue;
			}
			if (inQuote) {
				tmpBuffer.append(c);
				continue;
			}
			if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
				if (count != 0) {
					encode(lastTag, count, compiledPattern);
					lastTag = -1;
					count = 0;
				}
				if (c < 128) {
					// In most cases, c would be a delimiter, such as ':'.
					compiledPattern
							.append((char) (TAG_QUOTE_ASCII_CHAR << 8 | c));
				} else {
					// Take any contiguous non-ASCII alphabet characters and
					// put them in a single TAG_QUOTE_CHARS.
					int j;
					for (j = i + 1; j < length; j++) {
						char d = pattern.charAt(j);
						if (d == '\''
								|| (d >= 'a' && d <= 'z' || d >= 'A'
										&& d <= 'Z')) {
							break;
						}
					}
					compiledPattern
							.append((char) (TAG_QUOTE_CHARS << 8 | (j - i)));
					for (; i < j; i++) {
						compiledPattern.append(pattern.charAt(i));
					}
					i--;
				}
				continue;
			}

			int tag;
			if ((tag = patternChars.indexOf(c)) == -1) {
				throw new IllegalArgumentException("Illegal pattern character "
						+ "'" + c + "'");
			}
			if (lastTag == -1 || lastTag == tag) {
				lastTag = tag;
				count++;
				continue;
			}
			encode(lastTag, count, compiledPattern);
			lastTag = tag;
			count = 1;
		}

		if (inQuote) {
			throw new IllegalArgumentException("Unterminated quote");
		}

		if (count != 0) {
			encode(lastTag, count, compiledPattern);
		}

		// Copy the compiled pattern to a char array
		int len = compiledPattern.length();
		char[] r = new char[len];
		compiledPattern.getChars(0, len, r, 0);
		return r;
	}

	/**
	 * Encodes the given tag and length and puts encoded char(s) into buffer.
	 */
	private static final void encode(int tag, int length, StringBuilder buffer) {
		if (length < 255) {
			buffer.append((char) (tag << 8 | length));
		} else {
			buffer.append((char) ((tag << 8) | 0xff));
			buffer.append((char) (length >>> 16));
			buffer.append((char) (length & 0xffff));
		}
	}
}
